package com.digital.welcome.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.digital.welcome.entity.*;
import com.digital.welcome.mapper.*;
import com.digital.welcome.pojo.ApplicationState;
import com.digital.welcome.response.Result;
import com.digital.welcome.service.*;
import com.digital.welcome.token.JwtToken;
import com.digital.welcome.util.DataEncode;
import com.digital.welcome.util.ExcelDataUtil;
import com.digital.welcome.util.JwtUtil;
import com.digital.welcome.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.poifs.filesystem.FileMagic;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Pattern;


@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserCollegeMapper userCollegeMapper;

    @Autowired
    private MajorClassMapper majorClassMapper;

    @Autowired
    private CollegeMapper collegeMapper;
    @Autowired
    private DataEncode dataEncode;

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private UserLogService userLogService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private UserCommunicationMapper userCommunicationMapper;

    private final Lock Lock = new ReentrantLock();

    @Override
    public String login(User user, HttpServletRequest request) {
//        String code = null;
//        String ip=request.getRemoteAddr();//获取请求客户端的IP地址
//        try
//        {
//            code = user.getName().toLowerCase();
//        } catch (Exception e)
//        {
//            return JSON.toJSONString(new Result<>().setCode(0).setMessage("请输入验证码"));
//        }
//
//        HttpSession session = request.getSession();
//        String verifyCode = null;
//        try
//        {
//            verifyCode= session.getAttribute("verifyCode").toString().toLowerCase();
//        } catch (NullPointerException e)
//        {
//            return JSON.toJSONString(new Result<>().setCode(0).setMessage("验证码过期，请刷新！"));
//        }
//
//        if (!code.equals(verifyCode))
//        {
//            return JSON.toJSONString(new Result<>().setCode(0).setMessage("验证码错误"));
//        }
//        账号密码base64解密
        String userPassword = dataEncode.decodeBae64(user.getUserPassword());
        String userName = dataEncode.decodeBae64(user.getUserName());
        userPassword = dataEncode.encodeMD5(userPassword);
        // 获得当前用户，状态未认证
        Subject subject = SecurityUtils.getSubject();
        String token = JwtUtil.createJWT(userName, "back", "user", 1000 * 60 * 60 * 24);
        JwtToken jwtToken = new JwtToken(token, userPassword);
        // UsernamePasswordToken用户密码临牌
        try {
            subject.login(jwtToken);// 这个token传给了自定义Realm的doGetAuthenticationInfo方法入参；
            Map<String, Object> map = new HashMap<>();
            User backUser = userMapper.getUserByUsername(userName);
            map.put("user", backUser);
            map.put("token", token);
            log.info("用户【" + userName + "】登录");
            insertUserLog(user, request);
            return JSON.toJSONString(new Result<>().setCode(200).setMessage("登录成功").setData(map));

        } catch (UnknownAccountException e) {//用户名查不存在,异常
            return JSON.toJSONString(new Result<>().setCode(400).setMessage("用户不存在"));
        } catch (IncorrectCredentialsException e) {//密码不正确,异常
            return JSON.toJSONString(new Result<>().setCode(401).setMessage("密码不正确"));
        }
    }

    @Async
    public void insertUserLog(User user, HttpServletRequest request) {
        userLogService.insertUserLog(user, request);
    }


    @Override
    public User getUserByUsername(String username) {
        return userMapper.getUserByUsername(username);
    }

    @Override
    public String getUserById(User user) {
        User newUser = userMapper.selectById(user.getId());
        if (newUser == null) {
            return JSON.toJSONString(new Result<>().setCode(0).setMessage("用户不存在"));
        }
        return JSON.toJSONString(new Result<>().setCode(1).setMessage("查询成功").setData(newUser));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String insertUser(User user) {
        UserRole userRole = new UserRole();
        UserCollege userCollege = new UserCollege();
        user.setUserPassword(dataEncode.encodeMD5(user.getUserPassword()));
        if (userMapper.selectOne(new QueryWrapper<User>().eq("user_name", user.getUserName())) == null) {
            userMapper.insert(user);
        }
        /*
        赋权
        */
        if (userMapper.getOneUserByClasses(user.getUserName(), "2019") != null) {
            userRole.setRoleId(1);
            userRole.setUserName(user.getUserName());
            if (userRoleMapper.selectRoleByUserName(userRole.getUserName()) == null) {
                userRoleMapper.insert(userRole);
            }
        } else {
            userRole.setRoleId(6);
            userRole.setUserName(user.getUserName());
            if (userRoleMapper.selectRoleByUserName(userRole.getUserName()) == null) {
                userRoleMapper.insert(userRole);
            }
            return JSON.toJSONString(new Result<>().setCode(200).setMessage("插入成功"));
        }

        QueryWrapper<MajorClass> majorClassQueryWrapper = new QueryWrapper<>();
        majorClassQueryWrapper.eq("major", user.getMajor());
        majorClassQueryWrapper.eq("major_class_name", user.getClasses());
        MajorClass majorClass = majorClassMapper.selectOne(majorClassQueryWrapper);
        if (majorClass == null) {
            return JSON.toJSONString(new Result<>().setCode(400).setMessage("班级专业不存在"));
        }
        QueryWrapper<College> collegeQueryWrapper = new QueryWrapper<>();
        collegeQueryWrapper.eq("college", user.getCollege());
        College college = collegeMapper.selectOne(collegeQueryWrapper);
        if (college == null) {
            return JSON.toJSONString(new Result<>().setCode(400).setMessage("学院不存在"));
        }
        userCollege.setMajorId(majorClass.getMajorId())
                .setUserName(user.getUserName())
                .setCollegeId(college.getCollegeId());
        QueryWrapper<UserCollege> userCollegeQueryWrapper = new QueryWrapper<>();
        userCollegeQueryWrapper.eq("college_id", userCollege.getCollegeId());
        userCollegeQueryWrapper.eq("major_id", userCollege.getMajorId());
        userCollegeQueryWrapper.eq("user_name", userCollege.getUserName());
        if (userCollegeMapper.selectOne(userCollegeQueryWrapper) == null) {
            userCollegeMapper.insert(userCollege);
        }

        return JSON.toJSONString(new Result<>().setCode(200).setMessage("插入成功"));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String insertUsers(HttpServletRequest request) throws Exception {
        MultipartHttpServletRequest params;
        List<MultipartFile> multipartFiles;
        File file1;
        try {
            params = (MultipartHttpServletRequest) request;
            multipartFiles = params.getFiles("uploadFile");
            MultipartFile file = multipartFiles.get(0);
            file1 = ExcelDataUtil.multipartFileToFile(file);
            if (file1 == null) {
                throw new IOException();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return JSON.toJSONString(new Result<>().setCode(400).setMessage("excel读取错误，请检查是否选择正确"));
        }
        InputStream inputStream = FileMagic.prepareToCheckMagic(new FileInputStream(file1));//根据Excel魔数判断该文件是否为Excel文件
        if (ExcelDataUtil.isExcelFile(inputStream)) {
            List<String> user_sophomore = new ArrayList<>();
            List<String> user_freshman = new ArrayList<>();
            List<User> userList = ExcelDataUtil.userExcelDataRead(file1);
            Pattern p = Pattern.compile("2019");
            for (User u : userList) {
                insertUser(u);
                if (p.matcher(u.getClasses()).find()) {
                    user_freshman.add(u.getUserName());
                } else {
                    user_sophomore.add(u.getUserName());
                }
            }
            if (user_freshman.size() != user_sophomore.size()) {
                return JSON.toJSONString(new Result<>().setCode(400).setMessage("新生数于高年级数不匹配"));
            } else {
                UserCommunication userCommunication = new UserCommunication();
                for (int i = 0; i < user_freshman.size(); i++) {
                    userCommunication.setUserFreshman(user_freshman.get(i));
                    userCommunication.setUserSophomore(user_sophomore.get(i));
                    if (userCommunicationMapper.selectOne(new QueryWrapper<UserCommunication>()
                            .eq("user_freshman", userCommunication.getUserFreshman())) == null) {
                        userCommunicationMapper.insert(userCommunication);
                    }
                }
            }
            return JSON.toJSONString(new Result<>().setCode(200).setMessage("批量插入成功"));
        }
        return JSON.toJSONString(new Result<>().setCode(400).setMessage("不是excel文件"));
    }

    private void userCommunicationInsert(User u, List<String> user_sophomore, List<String> user_freshman) {
        if ("2019".matches(String.valueOf(u.getClass()))) {
            user_freshman.add(u.getUserName());
        } else {
            user_sophomore.add(u.getUserName());
        }
    }

    @Override
    public String getProvinceNumber(String province) {
        Integer count;
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("province", province);
        count = userMapper.selectCount(queryWrapper);
        return JSON.toJSONString(new Result<>().setCode(200).setMessage("查询成功").setData(count));
    }

    @Override
    public List<Permission> getMenuList(String username) {
        List<Permission> list;
        list = permissionMapper.selectAllPermissionByUsername(username);
        return list;

    }

    @Override
    public String getAllProvinces() {
        List<Object> provinces;
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.isNotNull("province");
        queryWrapper.select("distinct province");
        provinces = userMapper.selectObjs(queryWrapper);
        return JSON.toJSONString(new Result<>().setCode(400).setMessage("查询成功").setData(provinces));
    }

    @Override
    public String getStudentNumber() {
        Integer male;
        Integer female;
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("sex", "男");
        male = userMapper.selectCount(queryWrapper);

        QueryWrapper<User> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("sex", "女");
        female = userMapper.selectCount(queryWrapper2);
        Map<String, Integer> sexMap = new HashMap<>();
        sexMap.put("boy", male);
        sexMap.put("girl", female);
        return JSON.toJSONString(new Result<>().setCode(1).setMessage("查询成功").setData(sexMap));
    }

    @Override
    public String getUsername(User user) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("identity", user.getIdentity());
        User user1 = userMapper.selectOne(queryWrapper);
        if (user1 == null) {
            return JSON.toJSONString(new Result<>().setCode(0).setMessage("无该学生"));
        }
        return JSON.toJSONString(new Result<>().setCode(1).setMessage("查询成功").setData(user1.getUserName()));
    }

    @Override
    public String updatePassword(String username, String name, String identity, String newPassword) {
        String userName = dataEncode.decodeBae64(username);
        String nameNow = dataEncode.decodeBae64(name);
        String identityNow = dataEncode.decodeBae64(identity);
        User user = userMapper.getUserByUsername(userName);
        if (user == null) {
            return JSON.toJSONString(new Result<>().setCode(400).setMessage("用户不存在"));
        }
        if (!nameNow.equals(user.getName())) {
            return JSON.toJSONString(new Result<>().setCode(400).setMessage("不是你的姓名"));
        }
        if (!identityNow.equals(user.getIdentity())) {
            return JSON.toJSONString(new Result<>().setCode(400).setMessage("身份证号码不对"));
        }
        String passWord = dataEncode.encodeMD5(dataEncode.decodeBae64(newPassword));
        boolean res = userMapper.updateUserPassword(userName, passWord);
        if (res) {
            return JSON.toJSONString(new Result<>().setCode(200).setMessage("修改成功"));
        } else {
            return JSON.toJSONString(new Result<>().setCode(400).setMessage("修改失败"));
        }

    }


    @Autowired
    private UserUseService userUseService;
    @Autowired
    private UserCheckInService userCheckInService;
    @Autowired
    private UserLessPayService userLessPayService;
    @Autowired
    private ApplicationService applicationService;
    @Autowired
    private PayService payService;

    @Override
    public String getState(User user) {
        if (user == null) {
            return JSON.toJSONString(new Result<>().setCode(0).setMessage("用户名为空"));
        }
        String userName = user.getUserName();
        ApplicationState state = new ApplicationState();
        state.setUse(userUseService.selectState(userName));
        state.setCheckIn(userCheckInService.selectState(userName));
        state.setLessPay(userLessPayService.selectState(userName));
        state.setApplication(applicationService.getState(userName));
        state.setPay(payService.getState(userName));
        return JSON.toJSONString(new Result<>().setCode(1).setMessage("查询成功").setData(state));
    }

    @Override
    public String selectUser(String userName) throws InterruptedException {
        Object user = redisUtil.get("selfinformation" + userName);
        if (user == null) {
            if (Lock.tryLock()) {
                try {
                    User newUser = userMapper.getUserByUsername(userName);
                    if (newUser == null) {
                        redisUtil.set("selfinformation" + userName, "null", 10);
                        return JSON.toJSONString(new Result<>().setCode(400).setMessage("无此用户"));
                    } else {
                        redisUtil.set("selfinformation" + userName, newUser, 60 * 10);
                        return JSON.toJSONString(new Result<>().setCode(200).setMessage("查询成功").setData(newUser));
                    }
                } finally {
                    Lock.unlock();//释放锁
                }
            } else {
                Object another = redisUtil.get("selfinformation" + userName);
                if (another == null) {
                    Thread.sleep(100);
                    return selectUser(userName);
                } else {
                    return JSON.toJSONString(new Result<>().setCode(200).setMessage("查询成功").setData(another));
                }
            }
        }
        return JSON.toJSONString(new Result<>().setCode(200).setMessage("查询成功").setData(user));
    }

    @Override
    public String delete(String userName) {
        try {
            userMapper.delete(new QueryWrapper<User>().eq("user_name", userName));
            userRoleMapper.delete(new QueryWrapper<UserRole>().eq("user_name", userName));
            userCollegeMapper.delete(new QueryWrapper<UserCollege>().eq("user_name", userName));
            return JSON.toJSONString(new Result<>().setCode(200).setMessage("删除成功"));
        } catch (Exception e) {
            return JSON.toJSONString(new Result<>().setCode(200).setMessage("删除失败"));
        }
    }

    @Autowired
    private RoleMapper roleMapper;

    @Override
    public String updateRole(String userName, String roleName) {
        Integer roleId = roleMapper.selectOne(new QueryWrapper<Role>().eq("role_name", roleName)).getRoleId();
        int res = roleMapper.update(userName, roleId);
        if (res == 1) {
            return JSON.toJSONString(new Result<>().setCode(200).setMessage("修改成功"));
        } else {
            return JSON.toJSONString(new Result<>().setCode(200).setMessage("修改失败"));
        }

    }

    @Override
    public String insertManager(String userName, String passWord, String roleName) {
        if (userMapper.selectOne(new QueryWrapper<User>().eq("user_name", userName)) != null) {
            return JSON.toJSONString(new Result<>().setCode(400).setMessage("存在相同用户名"));
        }
        System.out.println(passWord);
        passWord = dataEncode.encodeMD5(passWord);
        User user = new User();
        user.setUserName(userName);
        user.setUserPassword(passWord);
        userMapper.insert(user);
        QueryWrapper<Role> wrapper = new QueryWrapper<>();
        Role role = roleMapper.selectOne(wrapper.eq("role_name", roleName));
        UserRole userRole = new UserRole();
        userRole.setRoleId(role.getRoleId());
        userRole.setUserName(userName);
        userRoleMapper.insert(userRole);
        return JSON.toJSONString(new Result<>().setCode(200).setMessage("新增成功"));
    }

    @Override
    public String deleteManager(String userName) {
        int roleId = roleMapper.selectRoleIdByUserName(userName);
        if (roleId == 1) {
            userCollegeMapper.delete(new QueryWrapper<UserCollege>().eq("user_name", userName));
        }
        userMapper.delete(new QueryWrapper<User>().eq("user_name", userName));
        userRoleMapper.delete(new QueryWrapper<UserRole>().eq("user_name", userName));
        return JSON.toJSONString(new Result<>().setCode(200).setMessage("删除成功"));
    }

    @Override
    public String getManager() {
        List<UserRole> userRoles = userRoleMapper.selectManager();
        for (UserRole userRole : userRoles) {
            Role role = roleMapper.selectOne(new QueryWrapper<Role>().eq("role_id", userRole.getRoleId()));
            userRole.setRoleName(role.getRoleName());
        }
        return JSON.toJSONString(new Result<>().setCode(200).setData(userRoles));
    }

    @Override
    public String findPage(PageRequest pageRequest) {

        HashMap<String, Object> map = new HashMap<>();
        if (pageRequest.getPageNum() <= 1) {
            pageRequest.setPageNum(1);
        }
        int offset = (pageRequest.getPageNum() - 1) * pageRequest.getPageSize();
        List<UserRole> userRoles = userRoleMapper.selectAllUserAndRoleName(offset, pageRequest.getPageSize());
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        int count = userMapper.selectCount(queryWrapper);
        map.put("list", userRoles);
        map.put("total", count);

        return JSON.toJSONString(new Result<>().setCode(1).setMessage("查询成功").setData(map));
    }
}
